#include "FreeRTOS_demo.h"

uint16_t S[Num];
float out_High = 3.0f;
uint16_t ADC_value[ADC_NUM];

#define ALL_TASK_DEPTH 64
#define ALL_TASK_PRIORITY 5
TaskHandle_t ALL_Task_handler;
void ALL_Task(void *pvParameters);

#define LED_TOGGLE_DEPTH 16
#define LED_TOGGLE_PRIORITY 5
TaskHandle_t LED_Toggle_handler;
void LED_Toggle(void *pvParameters);

#define DAC_TASK_DEPTH 128
#define DAC_TASK_PRIORITY 6
TaskHandle_t DAC_TASK_hander;
void DAC_TASK(void *pvParameters);

#define ADC_TASK_DEPTH 128
#define ADC_TASK_PRIORITY 4
TaskHandle_t ADC_TASK_hander;
void ADC_Task(void *pvParameters); 

void FreeRTOS_start(void)
{
    xTaskCreate((TaskFunction_t) ALL_Task,
                (char *) "all_task",
                (configSTACK_DEPTH_TYPE) ALL_TASK_DEPTH,
                (void *) NULL,
                (UBaseType_t) ALL_TASK_PRIORITY,
                (TaskHandle_t*) &ALL_Task_handler);
    vTaskStartScheduler();
}

void ALL_Task(void *pvParameters)
{
    taskENTER_CRITICAL();
    xTaskCreate((TaskFunction_t) LED_Toggle,
                (char *) "led_toggle",
                (configSTACK_DEPTH_TYPE) LED_TOGGLE_DEPTH,
                (void *) NULL,
                (UBaseType_t) LED_TOGGLE_PRIORITY,
                (TaskHandle_t*) &LED_Toggle_handler);
    xTaskCreate((TaskFunction_t)DAC_TASK,
                (char *)"DAC_task",
                (configSTACK_DEPTH_TYPE)DAC_TASK_DEPTH,
                (void *)NULL,
                (UBaseType_t)DAC_TASK_PRIORITY,
                (TaskHandle_t*)&DAC_TASK_hander);
    xTaskCreate((TaskFunction_t)ADC_Task,
                (char *)"ADC_task",
                (configSTACK_DEPTH_TYPE)ADC_TASK_DEPTH,
                (void *)NULL,
                (UBaseType_t)ADC_TASK_PRIORITY,
                (TaskHandle_t*)&ADC_TASK_hander);
    taskEXIT_CRITICAL();
    vTaskDelete(NULL);
}

void LED_Toggle(void *pvParameters)
{
    while (1)
    {
        HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
        vTaskDelay(500);
    }
}

void DAC_TASK(void *pvParameters)
{
    static char* WaveName[] = {
        "Sinusoid",    
        "Rectangular",
        "Zigzag",
        "Triangle",
        "Trapezoidal"  
    };
    static float out_Hz;
    while (1)
    {
        switch (Key_mark)
        {
        case 0:{
        Generate_Sine(0.0f,out_High,S);
        }break;
        case 1:{
        Generate_Rectangular(0.0f,out_High,0.5f,S);
        }break;
        case 2:{
        Generate_AsymTriangle(0.0f,out_High,0.01f,S);
        }break;
        case 3:{
        Generate_Triangle(0.0f,out_High,S);
        }break;
        case 4:{
        Generate_Trapezoid(0.0f,out_High,0.5f,0.5f,S);
        }break;
        default:
        Key_mark = 0;
        break;
        }
        HAL_DAC_Start_DMA(&hdac1,DAC_CHANNEL_1,(uint32_t*)&S,Num,DAC_ALIGN_12B_R);
        out_Hz = 1000000.0f/(float)DAC_CP_HZ;
        OLED_ShowNum(88,1,(unsigned int)out_Hz,4,16,0);
        OLED_ShowString(1,1,WaveName[Key_mark],16,0);
        vTaskDelay(200);
    }
}

void ADC_Task(void *pvParameters)
{
    HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
    static int index = 0;
    static float pre_value = 0;
    // HAL_ADC_Start_IT(&hadc1);
    HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
    HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&ADC_value,ADC_NUM);
		vTaskDelay(100);
    while (1)
    {
    //OLED_ShowNum(1,3,ADC_value,6,16,0);
    for (int i = 0; i < ADC_NUM; i++)
    {
    float cur_value = ((float)ADC_value[i] / 4096.0f * 32.0f) + 32.0f;
    HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&ADC_value,ADC_NUM);
    OLED_DrawLine(index+1,32,index+1,64,0);
    OLED_DrawLine(index,pre_value,++index,cur_value,1);
    pre_value = cur_value;
    if (index > 128)    
        {
        index = 0;
        }
    }
    vTaskDelay(200);
    }
}
